package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Subject;
import com.wzcl.app.dao.repository.SubjectRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.dto.SubjectDto;
import com.wzcl.app.service.SubjectService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Log4j2
@Service
public class SubjectServiceImpl implements SubjectService {

    @Autowired
    private SubjectRepository subjectRepository;

    @Override
    @CacheEvict(value = "Subject", allEntries = true)
    public Subject addSubject(SubjectDto subjectDto) {
        Subject subject = new Subject();
        BeanUtils.copyProperties(subjectDto, subject, "id");
        return subjectRepository.save(subject);
    }

    @Override
    @CacheEvict(value = "Subject", allEntries = true)
    public Subject delSubjectById(Integer id) {
        //校验获取
        Subject subject = getAndCheckById(id);
        //删除
        log.info("Subject:{} Physical deletion", JSON.toJSONString(subject));
        subjectRepository.delete(subject);
        return subject;
    }

    @Override
    @CacheEvict(value = "Subject", allEntries = true)
    public Subject updateSubject(SubjectDto subjectDto) {
        //校验获取
        Subject subject = getAndCheckById(subjectDto);
        //修改
        BeanUtils.copyProperties(subjectDto, subject, "id");
        return subjectRepository.save(subject);
    }

    @Override
    @Cacheable(value = "Subject", keyGenerator = "cacheKeyGenerator")
    public Subject getSubjectById(Integer id) {
        Optional<Subject> optional = subjectRepository.findById(id);
        return optional.orElse(null);
    }

    @Override
    @Cacheable(value = "Subject", keyGenerator = "cacheKeyGenerator")
    public Subject getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少课程ID");
        }
        Subject subject = getSubjectById(id);
        if (subject == null) {
            throw new BusinessException(CodeMsg.SUBJECT_NOT_EXIST);
        }
        return subject;
    }

    @Override
    @Cacheable(value = "Subject", keyGenerator = "cacheKeyGenerator")
    public List<Subject> getSubjectList(SubjectDto subjectDto) {
        return subjectRepository.findAll(getSpecification(subjectDto), subjectDto.getSort());
    }

    private Specification<Subject> getSpecification(SubjectDto subjectDto) {
        return new Specification<Subject>() {
            @Override
            public Predicate toPredicate(Root<Subject> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }

}
